#ifndef I2C_H
#define I2C_H

#ifndef TRUE
#define TRUE 	1
#endif

#ifndef FALSE
#define FALSE 	0
#endif


#define I2C_SEND_DATA_BUFFER_SIZE       0x20
#define I2C_RECEIVE_DATA_BUFFER_SIZE    0x20

// defines and constants
#define TWCR_CMD_MASK       0x0F
#define TWSR_STATUS_MASK    0xF8

// types
typedef enum
{
    I2C_IDLE 		= 0,
	I2C_BUSY 		= 1,
    I2C_MASTER_TX 	= 2,
	I2C_MASTER_RX 	= 3,
    I2C_SLAVE_TX 	= 4,
	I2C_SLAVE_RX 	= 5
} eI2cStateType;

typedef enum
{
    I2C_NONE 		= 0,
	I2C_NACK        = 1,
	I2C_ARB_LOST    = 2,
	I2C_SR_STOP     = 3,
	I2C_BUS_ERROR   = 4
} eI2cErrorType;


// functions

//! Initialize I2C (TWI) interface
void i2cInit(void);

//! Set the I2C transaction bitrate (in KHz)
void i2cSetBitrate(unsigned int bitrateKHz);

// I2C setup and configurations commands
//! Set the local (AVR processor's) I2C device address
void i2cSetLocalDeviceAddr(unsigned char deviceAddr, unsigned char genCallEn);

//! Set the user function which handles receiving (incoming) data as a slave
void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(unsigned char receiveDataLength, unsigned char* recieveData));
//! Set the user function which handles transmitting (outgoing) data as a slave
void i2cSetSlaveTransmitHandler(unsigned char (*i2cSlaveTx_func)(unsigned char transmitDataLengthMax, unsigned char* transmitData));

// Low-level I2C transaction commands 
//! Send an I2C start condition in Master mode
void i2cSendStart(void);
//! Send an I2C stop condition in Master mode
void i2cSendStop(void);
//! Wait for current I2C operation to complete
void i2cWaitForComplete(void);
//! Send an (address|R/W) combination or a data byte over I2C
void i2cSendByte(unsigned char data);
//! Receive a data byte over I2C  
// ackFlag = TRUE if recevied data should be ACK'ed
// ackFlag = FALSE if recevied data should be NACK'ed
void i2cReceiveByte(unsigned char ackFlag);
//! Pick up the data that was received with i2cReceiveByte()
unsigned char i2cGetReceivedByte(void);
//! Get current I2c bus status from TWSR
unsigned char i2cGetStatus(void);

// high-level I2C transaction commands
//! Get current I2c error status
eI2cErrorType i2cGetError(void);

//! send I2C data to a device on the bus
void i2cMasterSend(unsigned char deviceAddr, unsigned char length, unsigned char *data);
//! receive I2C data from a device on the bus
void i2cMasterReceive(unsigned char deviceAddr, unsigned char length, unsigned char* data);

//! receive I2C data from a device on the bus w/ send register address 
void i2cMasterTransfer(unsigned char deviceAddr, 
                            unsigned char sendlength, unsigned char* senddata, 
                            unsigned char receivelength, unsigned char* receivedata);

//! send I2C data to a device on the bus (non-interrupt based)
void i2cMasterSendNI(unsigned char deviceAddr, unsigned char length, unsigned char* data);
//! receive I2C data from a device on the bus (non-interrupt based)
void i2cMasterReceiveNI(unsigned char deviceAddr, unsigned char length, unsigned char *data);

void i2cMasterTransferNI(unsigned char deviceAddr, unsigned char sendlength, unsigned char* senddata, unsigned char receivelength, unsigned char* receivedata);
#endif
